package cn.sh.library.gmwx.controller;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.sh.library.gmwx.base.Constant;
import cn.sh.library.gmwx.bean.InstanceSearchBean;
import cn.sh.library.gmwx.bean.WorkSearchBean;
import cn.sh.library.gmwx.dto.Pager;
import cn.sh.library.gmwx.service.BookService;
import cn.sh.library.gmwx.service.RemoteService;
import cn.sh.library.gmwx.sparql.InstanceSparql;
import cn.sh.library.gmwx.sparql.ItemSparql;
import cn.sh.library.gmwx.sparql.WorkSparql;

@Controller
@RequestMapping("/")
public class BookController extends BaseController {
    @Resource
    private BookService bookService;
    @Resource
    private WorkSparql workSparql;
    @Resource
    private InstanceSparql instanceSparql;
    @Resource
    private ItemSparql itemSparql;
    @Resource
    private RemoteService remoteService;

    @ResponseBody
    @RequestMapping(value = "public/books/query", method = RequestMethod.POST)
    public Map<String, Object> query(Model model, WorkSearchBean search, Pager pager){
        Map<String, Object> result = new HashMap<>();

        List<Map<String, String>> list = this.bookService.list(search, pager);

        result.put("resultList", list);
        result.put("pager", pager);
        return result;
    }

    @RequestMapping(value = "view/{id}", method = RequestMethod.GET)
    public String view(Model model, @PathVariable("id") String id){
        String uri = Constant.PREFIX_WORK + id;
        model.addAttribute("uri", uri);

        model.addAttribute("info", this.workSparql.getWorkInfos(uri));

        model.addAttribute("cover", this.workSparql.getCoverHor(uri));

        return "public/view";
    }

    @ResponseBody
    @RequestMapping(value = "work/instances", method = RequestMethod.POST)
    public Map<String, Object> getInstances(Model model, InstanceSearchBean search, String workUri, Pager pager){
        Map<String, Object> result = new HashMap<>();
        if (StringUtils.isNotBlank(workUri)) {
            search.setWork(Constant.PREFIX_WORK + workUri.split("/view/")[1]);
        }

        List<Map<String, String>> list = this.bookService.instances(search, pager);

        result.put("resultList", list);
        result.put("pager", pager);
        return result;
    }

    @ResponseBody
    @RequestMapping(value = "getItems", method = RequestMethod.POST)
    public Map<String, Object> items(Model model, String instance_uri){
        Map<String, Object> result = new HashMap<>();

        List<Map<String, String>> list = this.itemSparql.getInstanceItems(instance_uri);
        result.put("resultList", list);

        return result;
    }

    @ResponseBody
    @RequestMapping(value = "public/remote/getRemotePersons", method = RequestMethod.POST)
    public Map<String, Object> getRemotePersons(Model model, String person, Pager pager) {
        Map<String, Object> result = new HashMap<>();

        List<Map<String, String>> list = this.workSparql.getRemotePersons(person);
        result.put("resultList", list);

        return result;
    }

    @ResponseBody
    @RequestMapping(value = "/rdf", method = RequestMethod.GET)
    public void rdf(HttpServletResponse response, String uri){
        ByteArrayOutputStream bos = (ByteArrayOutputStream) instanceSparql.instanceTempModel(uri);
        byte[] data = bos.toByteArray();
        String rdfData = new String(data, Charset.forName("utf-8"));

        response.setContentType("application/rdf+xml");
        try {
            response.getWriter().write(rdfData);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @ResponseBody
    @RequestMapping(value = "/manage/work_update_facet", method = RequestMethod.GET)
    public String updateFacet() {
        this.workSparql.updateFacetWork("bf:intendedAudience/bf:identifiedBy", "bf:IntendedAudience");
        this.workSparql.updateFacetWork("bf:genreForm/bf:identifiedBy", "bf:GenreForm");
        this.workSparql.updateFacetWork("bf:language/bf:identifiedBy", "bf:Language");
        this.workSparql.countWork();

        return "SUCCESS";
    }

    @ResponseBody
    @RequestMapping(value = "book/facet_aud", method = RequestMethod.POST)
    public Map<String, Object> facet_aud(Model model, WorkSearchBean search) {
        Map<String, Object> result = new HashMap<>();
        result.put("type", this.workSparql.countWorkFacet(search, "bf:intendedAudience/bf:identifiedBy"));

        return result;
    }

    @ResponseBody
    @RequestMapping(value = "book/facet_gen", method = RequestMethod.POST)
    public Map<String, Object> facet_gen(Model model, WorkSearchBean search) {
        Map<String, Object> result = new HashMap<>();
        result.put("type", this.workSparql.countWorkFacet(search, "bf:genreForm/bf:identifiedBy"));

        return result;
    }

    @ResponseBody
    @RequestMapping(value = "book/facet_lan", method = RequestMethod.POST)
    public Map<String, Object> facet_lan(Model model, WorkSearchBean search) {
        Map<String, Object> result = new HashMap<>();
        result.put("type", this.workSparql.countWorkFacet(search, "bf:language/bf:identifiedBy"));

        return result;
    }

    @ResponseBody
    @RequestMapping(value = "instance/facet", method = RequestMethod.POST)
    public Map<String, Object> instance_facet(Model model, InstanceSearchBean search, String workUri, String facet) {
        Map<String, Object> result = new HashMap<>();
        if (StringUtils.isNotBlank(workUri)) {
            search.setWork(Constant.PREFIX_WORK + workUri.split("/view/")[1]);
        }

        result.put("type", this.instanceSparql.countInstanceFacet(search, facet));

        return result;
    }

    @ResponseBody
    @RequestMapping(value = "book/count", method = RequestMethod.POST)
    public Map<String, Object> count(Model model, WorkSearchBean search){
        Map<String, Object> result = new HashMap<>();
        result.put("audience", this.workSparql.countWorkFacet(search, "bf:intendedAudience/bf:identifiedBy"));
        result.put("genre", this.workSparql.countWorkFacet(search, "bf:genreForm/bf:identifiedBy"));
        result.put("language", this.workSparql.countWorkFacet(search, "bf:language/bf:identifiedBy"));

        return result;
    }
}
